home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / DELIVER.C < prev    next >
C/C++ Source or Header  |  1991-11-24  |  31KB  |  768 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d e l i v e r  . c                                              */
  3. /*                                                                    */
  4. /*    UUPC/extended mail delivery subroutines                         */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Embedded Japanese support provided by Kenji Rikitake            */
  9. /*    28-AUG-1991                                                     */
  10. /*                                                                    */
  11. /*    On Japanese support:                                            */
  12. /*                                                                    */
  13. /*    Japanese MS-DOS uses a 2byte Kanji (Japanese ideogram) code     */
  14. /*    called "Shift-JIS".  This cannot be delivered via SMTP since    */
  15. /*    Shift-JIS maps its first byte from 0x80-0x9f and 0xe0-0xfc.     */
  16. /*    JUNET requests all hosts to send Kanji in a 7bit subset of      */
  17. /*    ISO2022.  This is commonly called "JIS 7bit".                   */
  18. /*                                                                    */
  19. /*    To provide Japanese functionality, you need to convert all      */
  20. /*    remote delivery messages to JIS 7bit, and all local delivery    */
  21. /*    messages to Shift-JIS.                                          */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. /*--------------------------------------------------------------------*/
  25. /*    Use a complex beep upon mail delivery if way to control the     */
  26. /*    speaker is available; if using MS C 6.0 under DOS, we can't     */
  27. /*    so don't try                                                    */
  28. /*--------------------------------------------------------------------*/
  29.  
  30. #ifdef __TURBOC__
  31. #define SMARTBEEP
  32. #endif
  33.  
  34. #ifdef FAMILYAPI
  35. #define SMARTBEEP
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <io.h>
  41. #include <ctype.h>
  42. #include <sys/types.h>
  43. #include <string.h>
  44. #include <process.h>
  45.  
  46. #ifdef __TURBOC__
  47. #include <dos.h>
  48. #endif
  49.  
  50. #ifdef FAMILYAPI
  51. #include <os2.h>
  52. #endif
  53.  
  54. #include "lib.h"
  55. #include "address.h"
  56. #include "deliver.h"
  57. #include "expath.h"
  58. #include "getseq.h"
  59. #include "kanjicnv.h"
  60. #include "hlib.h"
  61. #include "hostable.h"
  62. #include "import.h"
  63. #include "pushpop.h"
  64. #include "security.h"
  65. #include "usertabl.h"
  66.  
  67. #ifdef SMARTBEEP
  68. #include "ssleep.h"
  69. #endif
  70.  
  71. /*--------------------------------------------------------------------*/
  72. /*        Define current file name for panic() and printerr()         */
  73. /*--------------------------------------------------------------------*/
  74.  
  75. currentfile();
  76.  
  77. /*--------------------------------------------------------------------*/
  78. /*                        Internal prototypes                         */
  79. /*--------------------------------------------------------------------*/
  80.  
  81. static size_t DeliverLocal( const char *input,  /* Input file name    */
  82.                           char *user,     /* Target address           */
  83.                           boolean validate); /* Validate/forward
  84.                                                 local mail            */
  85.  
  86. static void trumpet( const char *tune);
  87.  
  88. static size_t DeliverRemote( const char *input, /* Input file name    */
  89.                              const char *address,  /* Target address  */
  90.                              const char *path);
  91.  
  92. static size_t DeliverGateway(   const char *input,
  93.                                 const char *user,
  94.                                 const char *node,
  95.                                 const struct HostTable *hostp);
  96.  
  97. static int CopyData(   const boolean remotedelivery,
  98.                        const char *input,
  99.                        FILE *mbox);
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*   Global (set by rmail.c) for number of hops this mail has seen    */
  103. /*--------------------------------------------------------------------*/
  104.  
  105.  INTEGER hops = 0;
  106.  
  107.  boolean remoteMail = FALSE;
  108.  
  109.  char *ruser = NULL;
  110.  char *rnode = NULL;
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*    D e l i v e r                                                   */
  114. /*                                                                    */
  115. /*    Deliver mail to one user                                        */
  116. /*--------------------------------------------------------------------*/
  117.  
  118. size_t Deliver(        const char *input,    /* Input file name       */
  119.                             char *address,  /* Target address           */
  120.                           boolean validate)  /* Validate/forward
  121.                                                 local mail            */
  122. {
  123.    char node[MAXADDR];
  124.    char path[MAXADDR];
  125.    char user[MAXADDR];
  126.    char *token;
  127.    struct HostTable *hostp;
  128.  
  129.    if (ruser == NULL)
  130.    {
  131.       sprintf(path,"%s!%s", fromnode, fromuser);
  132.       user_at_node(path, path, node, user);
  133.       ruser = strdup( user );
  134.       rnode = strdup( node );
  135.    }
  136.  
  137.    user_at_node(address, path, node, user);
  138.  
  139. /*--------------------------------------------------------------------*/
  140. /*                       Handle local delivery                        */
  141. /*--------------------------------------------------------------------*/
  142.  
  143.    if (equal(path, nodename)) /* Local node?                         */
  144.    {
  145.       if (equal(nodename, node)) /* Really the local node?           */
  146.          return DeliverLocal( input, user, validate );   /* Yes!     */
  147.       else {
  148.          printmsg(0,"Mail for \"%s\" via \"%s\" has no \
  149. delivery route, delivering to postmaster %s",
  150.                address, path , postmaster);
  151.          return Deliver( input, postmaster, TRUE);
  152.       } /* else */
  153.    }  /* if */
  154.  
  155. /*--------------------------------------------------------------------*/
  156. /*                    Do we need loop protection?                     */
  157. /*--------------------------------------------------------------------*/
  158.  
  159.    if (hops > maxhops)
  160.    {
  161.          printmsg(0,
  162.          "Mail for \"%s\" via \"%s\" has exceeded hop \
  163. limit of %d, delivering to postmaster %s",
  164.                address, path , maxhops, postmaster);
  165.          return Deliver( input, postmaster, TRUE);
  166.    }
  167.  
  168. /*--------------------------------------------------------------------*/
  169. /*                   Deliver to a gateway if needed                   */
  170. /*--------------------------------------------------------------------*/
  171.  
  172.    hostp = checkname( path );
  173.    if ( (hostp != BADHOST) && (hostp->hstatus == gatewayed))
  174.       return DeliverGateway( input, user, node, hostp );
  175.  
  176. /*--------------------------------------------------------------------*/
  177. /*         Deliver mail to a system directory connected to us         */
  178. /*--------------------------------------------------------------------*/
  179.  
  180.    if (equal(path,node))   /* Directly connected system?          */
  181.       return DeliverRemote( input, user, path); /* Yes            */
  182.  
  183. /*--------------------------------------------------------------------*/
  184. /*   Default delivery; strip any this node and the directly           */
  185. /*   connected system from the address, then deliver to the next      */
  186. /*   hop on the route                                                 */
  187. /*--------------------------------------------------------------------*/
  188.  
  189.    strcpy(node,address);
  190.    token = strtok(node,"!");  /* Get first host in path        */
  191.    if (equal( HostAlias(token), nodename))   /* Local system?  */
  192.    {
  193.       token =  strtok(NULL,"");  /* Yes --> Get rest of addr   */
  194.       strcpy(address, token);    /* Use it for address         */
  195.       token = strtok(token,"!"); /* Get next host in path      */
  196.    } /* if */
  197.  
  198.    if (equal( HostAlias(token), path ))  /* Next system?       */
  199.    {
  200.       token =  strtok(NULL,"");  /* Yes --> Get rest of addr   */
  201.       strcpy(address, token);    /* Use it for address         */
  202.    } /* if */
  203.  
  204.    if (!strpbrk(address,"!@"))   /* Any host delimiters?       */
  205.    {                             /* No --> Check for % routing */
  206.       token = strrchr(address,'%'); /* Get last percent sign   */
  207.       if (token != NULL)
  208.          *token = '@';           /* Make it an RFC-822 address */
  209.       else
  210.          printmsg(0,"Deliver: Cannot find node in \"%s\"",
  211.                address);         /* That's odd, it should not  */
  212.                                  /* be a local address!        */
  213.    } /* if */
  214.  
  215.    return DeliverRemote( input, address, path );
  216.  
  217. } /* Deliver */
  218.  
  219. /*--------------------------------------------------------------------*/
  220. /*    D e l i v e r L o c a l                                         */
  221. /*                                                                    */
  222. /*    Handle local delivery, including optional forwarding            */
  223. /*--------------------------------------------------------------------*/
  224.  
  225. static size_t DeliverLocal( const char *input,
  226.                                           /* Input file name          */
  227.                           char *user,     /* Target address           */
  228.                           boolean validate)  /* TRUE = validate,
  229.                                                 forward user's mail   */
  230. {
  231.    char mboxname[FILENAME_MAX];
  232.    FILE *mbox;
  233.    char buf[BUFSIZ];
  234.    char command[BUFSIZ];
  235.    struct UserTable *userp;
  236.    int delivered = 0;
  237.    boolean announce = FALSE;
  238.  
  239. /*--------------------------------------------------------------------*/
  240. /*    If the parameter is the postmaster, use the configuration       */
  241. /*    defined value for the postmaster                                */
  242. /*--------------------------------------------------------------------*/
  243.  
  244.    if (equali(user, POSTMASTER))
  245.       user = postmaster;
  246.  
  247. /*--------------------------------------------------------------------*/
  248. /*             Validate user id and check for forwarding              */
  249. /*--------------------------------------------------------------------*/
  250.  
  251.    if (validate)
  252.    {
  253.       validate = strcmp( postmaster , user);
  254.                                  /* Don't loop delivering to postmast*/
  255.       userp = checkuser(user);   /* Locate user id in host table     */
  256.       if ( userp == BADUSER )    /* Invalid user id?                 */
  257.       {                          /* Yes --> Dump in trash bin        */
  258.          printmsg(0,
  259.                "\"%s\" is an invalid user, delivering to %s",
  260.                user, postmaster);
  261.          return DeliverLocal( input, postmaster, validate);
  262.       } /* if */
  263.  
  264.  
  265. /*--------------------------------------------------------------------*/
  266. /*               The user id validated; handle the mail               */
  267. /*--------------------------------------------------------------------*/
  268.  
  269.       mkfilename(mboxname, userp->homedir, DOTFORWARD);
  270.       mbox = FOPEN(mboxname, "r", TEXT);
  271.  
  272.       if (mbox == NULL )         /* The .forward file exists?        */
  273.          announce = TRUE;        /* No --> Fall through              */
  274.       else {
  275.          while( fgets( buf , BUFSIZ , mbox) != NULL )
  276.          {
  277.             char c = *buf;
  278.             if ( buf[ strlen(buf) - 1 ]== '\n')
  279.                buf[ strlen(buf) - 1 ] = '\0';
  280.             printmsg(8,"Forwarding to \"%s\"", buf);
  281.             if ( isalpha( c ) && (buf[1] == ':'))  /* Drive name?    */
  282.                c = ':';             /* Yes --> special case          */
  283.  
  284.             switch(*buf)
  285.             {
  286.                case '\0':
  287.                   break;            /* Empty line, ignore         */
  288.  
  289.                case '|':               /* Pipe mail into a command   */
  290.                {
  291.                   long here = ftell(mbox);
  292.                   fclose(mbox);
  293.                   sprintf(command , "%s < %s", &buf[1], input);
  294.                   printmsg(1,"Executing \"%s\" in %s",
  295.                         command, userp->homedir);
  296.                   PushDir( userp->homedir );
  297.                   system(command);                 /* FIX THIS */
  298.                   PopDir();
  299.                   delivered += 1;
  300.                   mbox = FOPEN(mboxname, "r", TEXT);
  301.                   fseek( mbox, here, SEEK_SET);
  302.                   break;
  303.                } /* case */
  304.  
  305.                case '\\':              /* Deliver without forwarding */
  306.                   delivered += Deliver( input, &buf[1], FALSE );
  307.                   announce = TRUE;
  308.                   break;
  309.  
  310.                case '/':               /* Save in absolute path name */
  311.                case ':':
  312.                case '~':
  313.                   if (expand_path(buf, NULL, userp->homedir,
  314.                                   E_mailext) == NULL )
  315.                   {
  316.                      printmsg(0,
  317.                            "Invalid path in filename, delivering to %s",
  318.                            user, postmaster);
  319.                      return DeliverLocal( input, postmaster, validate );
  320.                   }
  321.                   else
  322.                      delivered += DeliverLocal( input, buf, FALSE );
  323.                   announce = TRUE;
  324.                   break;
  325.  
  326.                default:                /* Deliver normally           */
  327.                   delivered += Deliver( input, buf, validate );
  328.             } /* switch */
  329.          } /* while */
  330.  
  331.          fclose(mbox);
  332.  
  333.          if (announce)        /* Did we deliver mail locally?        */
  334.             trumpet( userp->beep);  /* Yes --> Inform the user       */
  335.          return delivered;
  336.  
  337.       } /* if */
  338.  
  339.    } /* if (validate) */
  340.  
  341. /*--------------------------------------------------------------------*/
  342. /*       The user is valid (or not validated) and not forwarded       */
  343. /*--------------------------------------------------------------------*/
  344.  
  345.    if ((*user == '/') || (isalpha( *user ) && user[1] == ':'))
  346.                               /* Absolute path from recursive call?   */
  347.       strcpy(mboxname, user); /* Yes --> Use it as-is                 */
  348.    else
  349.       mkmailbox(mboxname, user);
  350.                               /* No --> Build normal name             */
  351.  
  352.    printmsg(1,"Delivering mail from %s%s%s to %s",
  353.                         ruser,
  354.                         remoteMail ? "@" : "",
  355.                         remoteMail ? rnode : "",
  356.                          user );
  357.  
  358.    if ( announce )
  359.       trumpet( userp->beep);  /* Local delivery, inform the user     */
  360.  
  361.    mbox = FOPEN( mboxname , "a", TEXT );
  362.    if (mbox == NULL )
  363.    {
  364.       printerr(mboxname);
  365.       printmsg(0,"Cannot open mailbox \"%s\" for output",
  366.                   mboxname);
  367.    }
  368.  
  369.    if (!isatty(fileno(mbox)))
  370.       fputs(MESSAGESEP,mbox); /* Write separator line                 */
  371.  
  372.    return CopyData( FALSE, input , mbox );
  373.  
  374. } /* DeliverLocal */
  375.  
  376. /*--------------------------------------------------------------------*/
  377. /*    t r u m p e t                                                   */
  378. /*                                                                    */
  379. /*    Trumpet the arrival of remote mail to a local user              */
  380. /*--------------------------------------------------------------------*/
  381.  
  382. static void trumpet( const char *tune)
  383. {
  384. #ifdef SMARTBEEP
  385.    char buf[BUFSIZ];
  386.    char *token = buf;
  387.    size_t tone, duration;
  388. #endif
  389.  
  390.    if ((tune == NULL) || !remoteMail) /* Should we announce?  */
  391.       return;                 /* No --> Return quietly (literally)   */
  392.  
  393. /*--------------------------------------------------------------------*/
  394. /*             We are to announce the arrival of the mail             */
  395. /*--------------------------------------------------------------------*/
  396.  
  397. #ifdef SMARTBEEP
  398.    strcpy(buf,tune);          /* Save the data                       */
  399.  
  400.    while( (token = strtok( token, ",")) != NULL)
  401.    {
  402.       tone = (size_t) atoi(token);
  403.       token = strtok( NULL, ",");
  404.       duration = (token == NULL) ? 500 : (size_t) atoi(token);
  405. #ifdef __TURBOC__
  406.       if (tone == 0)
  407.          nosound();
  408.       else
  409.          sound( tone );
  410.       ddelay( duration );
  411. #else
  412.       if (tone == 0)
  413.          ddelay(duration);
  414.       else
  415.          DosBeep( tone, duration );
  416. #endif /* SMARTBEEP */
  417.       token = NULL;           /* Look at next part of string   */
  418.    } /* while */
  419.  
  420. #ifdef __TURBOC__
  421.    nosound();
  422. #endif
  423. #else
  424.  
  425. /*--------------------------------------------------------------------*/
  426. /*      We cannot play the requested tune; just beep at the user      */
  427. /*--------------------------------------------------------------------*/
  428.  
  429.    fputc('\a', stdout);
  430. #endif /* SMARTBEEP */
  431.  
  432. } /* trumpet */
  433.  
  434. /*--------------------------------------------------------------------*/
  435. /*    D e l i v e r G a t e w a y                                     */
  436. /*                                                                    */
  437. /*    Deliver mail via a gateway program                              */
  438. /*--------------------------------------------------------------------*/
  439.  
  440. static size_t DeliverGateway(   const char *input,
  441.                                 const char *user,
  442.                                 const char *node,
  443.                                 const struct HostTable *hostp)
  444. {
  445.    char command[BUFSIZ];
  446.  
  447. /*--------------------------------------------------------------------*/
  448. /*    Format the command and tell the user what we're going to do     */
  449. /*--------------------------------------------------------------------*/
  450.  
  451.    sprintf(command , "%s %s %s %s < %s",
  452.                      hostp->via,          /* Program to perform forward */
  453.                      hostp->hostname,     /* Nominal host routing via   */
  454.                      node ,               /* Final destination system   */
  455.                      user,                /* user on "node" for delivery*/
  456.                      input);              /* The data to forward        */
  457.  
  458.    printmsg(1,
  459.       "Gatewaying mail from %s@%s to %s@%s via %s using \"%s\"",
  460.        ruser, rnode, user, node, hostp->hostname, hostp->via);
  461.    printmsg(3,"DeliverGateway: %s",command);
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*  Run the command and return caller with count of mail delivered    */
  465. /*--------------------------------------------------------------------*/
  466.  
  467.    system(command);
  468.    return 1;
  469.  
  470. } /* DeliveryGateway */
  471.  
  472. /*--------------------------------------------------------------------*/
  473. /*    D e l i v e r R e m o t e                                       */
  474. /*                                                                    */
  475. /*    Queue mail for delivery on another system via UUCP              */
  476. /*--------------------------------------------------------------------*/
  477.  
  478. static size_t DeliverRemote( const char *input, /* Input file name    */
  479.                     const char *address,  /* Target address           */
  480.                     const char *path)
  481. {
  482.    static char *spool_fmt = SPOOLFMT;              /* spool file name */
  483.    static char *dataf_fmt = DATAFFMT;
  484.    static char *send_cmd  = "S %s %s %s - %s 0666\n";
  485.    static long seqno = 0;
  486.    static char *SavePath = NULL;
  487.    FILE *stream;              /* For writing out data                */
  488.    static char everyone[500]; /* 512, with room for "rmail "         */
  489.  
  490.    char msfile[FILENAME_MAX]; /* MS-DOS format name of files         */
  491.    char msname[22];           /* MS-DOS format w/o path name         */
  492.  
  493.    char tmfile[15];           /* Call file, UNIX format name         */
  494.    static char ixfile[15];    /* eXecute file for remote system,
  495.                                 UNIX format name for local system   */
  496.    static char idfile[15];    /* Data file, UNIX format name         */
  497.    static char rdfile[15];    /* Data file name on remote system,
  498.                                  UNIX format                         */
  499.    static char rxfile[15];    /* Remote system UNIX name of eXecute
  500.                                  file                                */
  501.  
  502.    printmsg(1,"Spooling mail from %s%s%s to %s via %s",
  503.                ruser,
  504.                remoteMail ? "@" : "",
  505.                remoteMail ? rnode : "",
  506.                address ,
  507.                path);
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*          Create the UNIX format of the file names we need          */
  511. /*--------------------------------------------------------------------*/
  512.  
  513.    if ((seqno == 0) ||
  514.        (SavePath == NULL) ||
  515.        !equal(SavePath, path) ||
  516.        ((int) (strlen(everyone) + strlen(address) + 2) > (int) sizeof everyone))
  517.    {
  518.       char *seq;
  519.       seqno = getseq();
  520.       seq = JobNumber( seqno );
  521.       if  (SavePath != NULL )
  522.       {
  523.          free(SavePath);
  524.          SavePath = NULL;
  525.       } /* if */
  526.       sprintf(tmfile, spool_fmt, 'C', path,     'A' , seq);
  527.       sprintf(idfile, dataf_fmt, 'D', nodename , seq, 'd');
  528.       sprintf(rdfile, dataf_fmt, 'D', nodename , seq, 'r');
  529.       sprintf(ixfile, dataf_fmt, 'D', nodename , seq, 'e');
  530.       sprintf(rxfile, dataf_fmt, 'X', nodename , seq, 'r');
  531.       strcpy(everyone,address);
  532.    } /* if */
  533.    else {
  534.       strcat(everyone," ");
  535.       strcat(everyone,address);
  536.    } /* else */
  537.  
  538. /*--------------------------------------------------------------------*/
  539. /*                     create remote X (xqt) file                     */
  540. /*--------------------------------------------------------------------*/
  541.  
  542.    importpath( msname, ixfile, path);
  543.    mkfilename( msfile, spooldir, msname);
  544.  
  545.    stream = FOPEN(msfile, "w", BINARY);
  546.    if ( stream == NULL )
  547.    {
  548.       printerr(msfile);
  549.       printmsg(0, "DeliverRemote: cannot open X file %s", msfile);
  550.       return 0;
  551.    } /* if */
  552.  
  553.  
  554.    fprintf(stream, "R %s %s\nU %s %s\nF %s\nI %s\nC rmail %s\n",
  555.                ruser, rnode,
  556.                (equal(HostAlias( nodename ) , fromnode ) ||
  557.                 equal(HostAlias( domain ) , fromnode )) ?
  558.                         fromuser : "uucp" , nodename,
  559.                rdfile, rdfile, everyone);
  560.    fclose(stream);
  561.  
  562.    if (SavePath != NULL)
  563.       return 1;
  564.  
  565. /*--------------------------------------------------------------------*/
  566. /*  Create the data file with the mail to send to the remote system   */
  567. /*--------------------------------------------------------------------*/
  568.  
  569.    importpath(msname, idfile, path);
  570.    mkfilename( msfile, spooldir, msname);
  571.  
  572.    stream = FOPEN(msfile, "w", BINARY);
  573.    if (stream == NULL )
  574.    {
  575.       printerr(msfile);
  576.       printmsg(0,
  577.                "DeliverRemote: Cannot open spool file \"%s\" for output",
  578.                 msfile);
  579.       return 0;
  580.    }
  581.  
  582.    if (!CopyData( TRUE, input , stream ))
  583.    {
  584.       remove( msfile );
  585.       return 0;
  586.    }
  587.  
  588. /*--------------------------------------------------------------------*/
  589. /*                     create local C (call) file                     */
  590. /*--------------------------------------------------------------------*/
  591.  
  592.    importpath( msname, tmfile, path);
  593.    mkfilename( msfile, spooldir, msname);
  594.  
  595.    stream = FOPEN(msfile, "w", TEXT);
  596.    if (stream == NULL)
  597.    {
  598.       printerr( msname );
  599.       printmsg(0, "DeliverRemote: cannot open C file %s", msfile);
  600.       return 0;
  601.    }
  602.  
  603.    fprintf(stream, send_cmd, idfile, rdfile,
  604.                (equal(HostAlias( nodename ) , fromnode ) ||
  605.                 equal(HostAlias( domain ) , fromnode )) ?
  606.                         fromuser : "uucp" ,
  607.                   idfile);
  608.    fprintf(stream, send_cmd, ixfile, rxfile,
  609.                (equal(HostAlias( nodename ) , fromnode ) ||
  610.                 equal(HostAlias( domain ) , fromnode )) ?
  611.                         fromuser : "uucp" ,
  612.                   ixfile);
  613.    fclose(stream);
  614.  
  615.    if (bflag[F_MULTI])        /* Deliver to multiple users at once?  */
  616.       SavePath = strdup(path);   /* Yes --> Save routing info        */
  617.  
  618.    return 1;
  619. } /* DeliverRemote */
  620.  
  621. /*--------------------------------------------------------------------*/
  622. /* C o p y D a t a                                                    */
  623. /*                                                                    */
  624. /* Copy data into its final resting spot                              */
  625. /*--------------------------------------------------------------------*/
  626.  
  627. static int CopyData( const boolean remotedelivery,
  628.                      const char *input,
  629.                      FILE *dataout)
  630. {
  631.    FILE *datain = FOPEN(input, "r", TEXT);
  632.    char buf[BUFSIZ];
  633.    int column = 0;
  634.    boolean success = TRUE;
  635.  
  636.    int (*put_string) (char *, FILE *) = (int (*)(char *, FILE *)) fputs;
  637.                               /* Assume no Kanji translation needed  */
  638.  
  639. /*--------------------------------------------------------------------*/
  640. /*                      Verify the input opened                       */
  641. /*--------------------------------------------------------------------*/
  642.  
  643.    if (datain == NULL)
  644.    {
  645.       printerr(input);
  646.       printmsg(0,"Unable to open input file \"%s\"", input);
  647.       fclose(dataout);
  648.       return 0;
  649.    } /* datain */
  650.  
  651. /*--------------------------------------------------------------------*/
  652. /*    When we do the From line, we also determine if we must          */
  653. /*    translate the data.  Note that the default is initialized to    */
  654. /*    fputs() above.                                                  */
  655. /*                                                                    */
  656. /*    If Kanji is not enabled, don't translate it                     */
  657. /*                                                                    */
  658. /*    If local mail queued for local delivery, the data is already    */
  659. /*    in Shift JIS, so don't translate it.                            */
  660. /*                                                                    */
  661. /*    If remote mail is queued for remote delivery, the data is       */
  662. /*    already in JIS 7bit, so don't translate it.                     */
  663. /*                                                                    */
  664. /*    If delivering remote mail locally, translate to Shift JIS       */
  665. /*                                                                    */
  666. /*    If delivering local mail remotely, translate to JIS 7 bit       */
  667. /*--------------------------------------------------------------------*/
  668.  
  669. /*--------------------------------------------------------------------*/
  670. /*                        Generate a FROM line                        */
  671. /*--------------------------------------------------------------------*/
  672.  
  673.    switch( (int) remoteMail * 2 + (int) remotedelivery )
  674.    {
  675.       case 3:                 /* Remote sender, remote delivery      */
  676.          strcpy( buf, fromuser );
  677.          strtok( buf, "!");   /* Get first host in list              */
  678.          if ( !equal(HostAlias( buf ), fromnode ))
  679.                               /* Host already in list?               */
  680.          {                    /* No --> Insert it                    */
  681.             fprintf(dataout, "From %s!%s %s remote from %s\n",
  682.                      fromnode,
  683.                      fromuser,
  684.                      now,
  685.                      nodename);
  686.             break;
  687.          }
  688.  
  689. /*--------------------------------------------------------------------*/
  690. /*    If the name to add and the first name in the path are the       */
  691. /*    same, fall through to case 2, which doesn't add the same        */
  692. /*    name on twice                                                   */
  693. /*                                                                    */
  694. /*    Note:  For the Kanji translation we re-check the                */
  695. /*    remoteDelivery flag since we do the fall through from above.    */
  696. /*--------------------------------------------------------------------*/
  697.  
  698.       case 2:                 /* Remote sender, local delivery       */
  699.          if ( bflag[ F_KANJI ] && !remotedelivery )
  700.                               /* Kanji from remote node?             */
  701.             put_string = (int (*)(char *, FILE *)) fputs_shiftjis;
  702.                               /* Yes --> Translate it                */
  703.  
  704.          fprintf(dataout, "From %s %s remote from %s\n",
  705.                   fromuser,
  706.                   now,
  707.                   fromnode);
  708.          break;
  709.  
  710.       case 1:                 /* Local sender, remote delivery       */
  711.          if ( bflag[F_KANJI]) /* Translation enabled?                */
  712.             put_string = (int (*)(char *, FILE *)) fputs_jis7bit;
  713.                               /* Translate into 7 bit Kanji          */
  714.  
  715.          column = strlen(domain) - 5;
  716.          if ((column > 0) && equali(&domain[column],".UUCP"))
  717.                               /* UUCP domain?                        */
  718.             fprintf(dataout, "From %s %s remote from %s\n",
  719.                   fromuser,   /* Yes --> Use simple address          */
  720.                   now,
  721.                   nodename);
  722.          else                 /* No --> Use domain address           */
  723.             fprintf(dataout, "From %s!%s %s remote from %s\n",
  724.                   domain,
  725.                   fromuser,
  726.                   now,
  727.                   nodename);
  728.          break;
  729.  
  730.       case 0:                 /* Local sender, local delivery        */
  731.          fprintf(dataout, "From %s %s\n",
  732.                   fromuser,
  733.                   now);
  734.          break;
  735.  
  736.    } /* switch */
  737.  
  738. /*--------------------------------------------------------------------*/
  739. /*                       Loop to copy the data                        */
  740. /*--------------------------------------------------------------------*/
  741.  
  742.    while (fgets(buf, BUFSIZ, datain) != NULL)
  743.    {
  744.       if ((*put_string)(buf, dataout) == EOF)     /* I/O error? */
  745.       {
  746.          printerr("output");
  747.          printmsg(0,"I/O error on \"%s\"", "output");
  748.          fclose(dataout);
  749.          return 0;
  750.       } /* if */
  751.    } /* while */
  752.  
  753. /*--------------------------------------------------------------------*/
  754. /*                      Close up shop and return                      */
  755. /*--------------------------------------------------------------------*/
  756.  
  757.    if (ferror(datain))        /* Clean end of file on input?         */
  758.    {
  759.       printerr(input);
  760.       clearerr(datain);
  761.       success = FALSE;
  762.    }
  763.  
  764.    fclose(datain);
  765.    fclose(dataout);
  766.    return success;
  767. } /* CopyData */
  768.